package 滑动窗口;

import java.util.Arrays;

/**
 * @PackageName: 滑动窗口
 * @ClassName: LeetCode1423
 * @Author: chen jinxu
 * @Date: 2022/8/15 23:37
 * @Description: //可获得的最大点数
 * 几张卡牌 排成一行，每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。
 * 每次行动，你可以从行的开头或者末尾拿一张卡牌，最终你必须正好拿 k 张卡牌。
 * 你的点数就是你拿到手中的所有卡牌的点数之和。
 * 给你一个整数数组 cardPoints 和整数 k，请你返回可以获得的最大点数。
 * <p>
 * 输入：cardPoints = [1,2,3,4,5,6,1], k = 3
 * 输出：12
 * <p>
 * 解释：第一次行动，不管拿哪张牌，你的点数总是 1 。但是，先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌，最终点数为 1 + 6 + 5 = 12 。
 * 输入：cardPoints = [2,2,2], k = 2
 * 输出：4
 * <p>
 * 解释：无论你拿起哪两张卡牌，可获得的点数总是 4 。
 * 输入：cardPoints = [9,7,7,9,7,7,9], k = 7
 * 输出：55
 * <p>
 * 解释：你必须拿起所有卡牌，可以获得的点数为所有卡牌的点数之和。
 * 输入：cardPoints = [1,1000,1], k = 1
 * 输出：1
 * <p>
 * 解释：你无法拿到中间那张卡牌，所以可以获得的最大点数为 1 。
 * 输入：cardPoints = [1,79,80,1,1,1,200,1], k = 3
 * 输出：202
 * <p>
 * 1 <= cardPoints.length <= 10^5
 * 1 <= cardPoints[i] <= 10^4
 * 1 <= k <= cardPoints.length
 */
public class LeetCode1423 {
    public static void main(String[] args) {
       // System.out.println(maxScore(new int[]{1, 2, 3, 4, 5, 6, 1}, 3));
        //System.out.println(maxScore(new int[]{2, 2, 2}, 2));
       // System.out.println(maxScore(new int[]{9, 7, 7, 9, 7, 7, 9}, 7));
        System.out.println(maxScore(new int[]{1, 1000, 1}, 1));
      //  System.out.println(maxScore(new int[]{1, 79, 80, 1, 1, 1, 200, 1}, 3));
       // System.out.println(maxScore(new int[]{96, 90, 41, 82 , 39, 74, 64, 50, 30}, 8));
    }

    public static int maxScore(int[] cardPoints, int k) {
        if (k == cardPoints.length || cardPoints.length == 1) {
            return Arrays.stream(cardPoints).sum();
        }
        int windowSize = cardPoints.length - k;
        int remainSum = 0;
        int result = Integer.MAX_VALUE;
        for (int left = 0, right = 0; right < cardPoints.length; right++) {
            remainSum += cardPoints[right];
            if (right >= windowSize - 1) {
                result = Math.min(result, remainSum);
                remainSum -= cardPoints[left];
                left++;
            }
        }
        return Arrays.stream(cardPoints).sum() - result;
    }
    public static int maxScore1(int[] cardPoints, int k) {
        int n = cardPoints.length;
        // 滑动窗口长度
        int windowSize = n - k;
        // 选择前 n-k个值作为初始值
        int sum = 0;
        for (int i = 0; i < windowSize; i++) {
            sum += cardPoints[i];
        }
        int minSum = sum;
        for (int i = windowSize; i < n; i++) {
            sum += cardPoints[i] - cardPoints[i - windowSize];
            minSum = Math.min(sum, minSum);
        }
        return Arrays.stream(cardPoints).sum() - minSum;
    }

}
